﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CCL.SocketMessage.Request
{
    /// <summary>
    /// 프로젝트에 Member 추가를 요청하는 Message의 Body를 제공합니다.
    /// </summary>
    public class RegistProjectMemberList : Body
    {
        /// <summary>
        /// 멤버롤 등록하고자 하는 ProjectID
        /// </summary>
        public int ProjectID { get; private set; }

        /// <summary>
        /// 프로젝트에 등록하고자 하는 회원의 Email List를 가져옵니다.
        /// </summary>
        public List<Member> MemberList { get; private set; }

        /// <summary>
        /// 직렬화된 byte 배열을 통해 RegistProjectMemberList 객체를 생성합니다.
        /// </summary>
        /// <param name="bytes">직렬화된 byte 배열</param>
        public RegistProjectMemberList(byte[] bytes)
        {
            int start = 0;

            ProjectID = BitConverter.ToInt32(bytes, start);
            start += sizeof(int);

            int remainedSize = bytes.Length - start;
            int tableSize = Member.TableSize;

            MemberList = new List<Member>();

            for (; start < remainedSize; start += tableSize)
            {
                byte[] tableBytes = new byte[tableSize];
                Array.Copy(bytes, start, tableBytes, 0, tableSize);

                Member member = new Member(tableBytes);
                MemberList.Add(member);
            }
        }

        /// <summary>
        /// 새로운 RegistProjectMemberList 객체를 생성합니다.
        /// </summary>
        /// <param name="memberList">등록하고자 하는 Project의 </param>
        public RegistProjectMemberList(int projectId, List<Member> memberList)
        {
            ProjectID = projectId;
            MemberList = memberList;
        }

        /// <summary>
        /// 바이트 배열로 직렬화 합니다.
        /// </summary>
        /// <returns>직렬화된 바이트 배열</returns>
        public override byte[] GetByte()
        {
            byte[] bytes = new byte[GetSize()];

            byte[] temp;
            int start = 0;

            temp = BitConverter.GetBytes(ProjectID);
            Array.Copy(temp, 0, bytes, start, temp.Length);
            start += temp.Length;

            foreach (Member member in MemberList)
            {
                temp = member.GetByte();
                Array.Copy(temp, 0, bytes, start, temp.Length);
                start += temp.Length;
            }

            return bytes;
        }

        /// <summary>
        /// 직렬화 가능한 객체의 바이트 사이즈를 가져옵니다.
        /// </summary>
        /// <returns>직렬화된 바이트 사이즈</returns>
        public override uint GetSize()
        {
            uint size = 0;

            size += sizeof(int);
            size += (uint)(MemberList.Count * Member.TableSize);

            return size;
        }

        /// <summary>
        /// 직렬화 가능한 등록하고자 하는 Member 정보를 담는 Table을 제공합니다.
        /// </summary>
        public class Member : TableStructure.Table, ISerializable
        {
            /// <summary>
            /// 등록하고자 하는 User Email
            /// </summary>
            public char[] Email { get; private set; }

            /// <summary>
            /// 해당 User의 Permission
            /// (Constant.Perm 참조)
            /// </summary>
            public byte Permission { get; private set; }

            /// <summary>
            /// 해당 Table의 총 Size
            /// </summary>
            public new const int TableSize = 
                Constant.Length.Email +         // Email
                sizeof(byte);                   // Permission

            /// <summary>
            /// 직렬화된 byte 배열을 통해 RegistMember 객체를 생성합니다.
            /// </summary>
            /// <param name="bytes">직렬화된 byte 배열</param>
            public Member(byte[] bytes)
            {
                int start = 0;

                Email = new char[Constant.Length.Email];
                Encoding.Default.GetChars(bytes, start, Constant.Length.Email, Email, 0);
                start += Constant.Length.Email;

                Permission = bytes[start];
            }

            /// <summary>
            /// 새로운 RegistMember 객체를 생성합니다.
            /// </summary>
            /// <param name="email">등록하고자 하는 User Email</param>
            /// <param name="perm">해당 User의 권한 (Constant.Perm 참조)</param>
            public Member(string email, Constant.Permission perm)
            {
                Email = CCL.Utility.StringUtility.StringCopy(email, Constant.Length.Email);
                Permission = (byte)perm;
            }

            /// <summary>
            /// 바이트 배열로 직렬화 합니다.
            /// </summary>
            /// <returns>직렬화된 바이트 배열</returns>
            public byte[] GetByte()
            {
                byte[] bytes = new byte[GetSize()];

                byte[] temp;
                int start = 0;

                temp = Encoding.Default.GetBytes(Email);
                Array.Copy(temp, 0, bytes, start, Constant.Length.Email);
                start += Constant.Length.Email;

                bytes[start] = Permission;

                return bytes;
            }

            /// <summary>
            /// 직렬화 가능한 객체의 바이트 사이즈를 가져옵니다.
            /// </summary>
            /// <returns>직렬화된 바이트 사이즈</returns>
            public uint GetSize()
            {
                return TableSize;
            }
        }
    }
}
